home *** CD-ROM | disk | FTP | other *** search
/ Magnum One / Magnum One (Mid-American Digital) (Disc Manufacturing).iso / d12 / stevie.arc / MISCCMDS.C < prev    next >
Text File  |  1990-01-10  |  9KB  |  405 lines

  1. /*
  2.  * STevie - ST editor for VI enthusiasts.    ...Tim Thompson...twitch!tjt...
  3.  *
  4.  * Extensive modifications by:  Tony Andrews       onecom!wldrdg!tony
  5.  * Turbo C 1.5 port by: Denny Muscatelli 061988
  6.  */
  7.  
  8. #include "stevie.h"
  9.  
  10. static    void    openfwd(), openbwd();
  11.  
  12. extern    int    did_ai;
  13.  
  14. /*
  15.  * opencmd
  16.  *
  17.  * Add a blank line above or below the current line.
  18.  */
  19.  
  20. void
  21. opencmd(dir, can_ai)
  22. int    dir;
  23. int    can_ai;            /* if true, consider auto-indent */
  24. {
  25.     if (dir == FORWARD)
  26.         openfwd(can_ai);
  27.     else
  28.         openbwd(can_ai);
  29. }
  30.  
  31. static void
  32. openfwd(can_ai)
  33. int    can_ai;
  34. {
  35.     LINE    *l;
  36.     LPTR    *next;
  37.     char    *s;        /* string to be moved to new line, if any */
  38.  
  39.     /*
  40.      * If we're in insert mode, we need to move the remainder of the
  41.      * current line onto the new line. Otherwise the new line is left
  42.      * blank.
  43.      */
  44.     if (State == INSERT)
  45.         s = &Curschar->linep->s[Curschar->index];
  46.     else
  47.         s = "";
  48.  
  49.     if ((next = nextline(Curschar)) == NULL)    /* open on last line */
  50.         next = Fileend;
  51.  
  52.     /*
  53.      * By asking for as much space as the prior line had we make sure
  54.      * that we'll have enough space for any auto-indenting.
  55.      */
  56.     if ((l = newline(strlen(Curschar->linep->s) + SLOP)) == NULL)
  57.         return;
  58.  
  59.     if (*s != NUL)
  60.         strcpy(l->s, s);        /* copy string to new line */
  61. #if 0
  62.     else if (can_ai && P(P_AI)) {
  63.         /*
  64.          * Auto-indent removed due to buggy implementation...
  65.          */
  66.          did_ai = TRUE;
  67.     }
  68. #endif
  69.  
  70.     if (State == INSERT)        /* truncate current line at cursor */
  71.         *s = NUL;
  72.             
  73.  
  74.     Curschar->linep->next = l;    /* link neighbors to new line */
  75.     next->linep->prev = l;
  76.  
  77.     l->prev = Curschar->linep;    /* link new line to neighbors */
  78.     l->next = next->linep;
  79.  
  80.     if (next == Fileend)            /* new line at end */
  81.         l->num = Curschar->linep->num + LINEINC;
  82.  
  83.     else if ((l->prev->num) + 1 == l->next->num)    /* no gap, renumber */
  84.         renum();
  85.  
  86.     else {                    /* stick it in the middle */
  87.         unsigned long    lnum;
  88.         lnum = ((long)l->prev->num + (long)l->next->num) / 2;
  89.         l->num = lnum;
  90.     }
  91.  
  92.     *Curschar = *nextline(Curschar);    /* cursor moves down */
  93.     Curschar->index = 0;
  94.  
  95.     s_ins(Cursrow+1, 1);    /* insert a physical line */
  96.  
  97.     updatescreen();        /* because Botchar is now invalid... */
  98.  
  99.     cursupdate();        /* update Cursrow before insert */
  100. }
  101.  
  102. static void
  103. openbwd(can_ai)
  104. int    can_ai;
  105. {
  106.     LINE    *l;
  107.     LPTR    *prev;
  108.  
  109.     prev = prevline(Curschar);
  110.  
  111.     if ((l = newline(strlen(Curschar->linep->s) + SLOP)) == NULL)
  112.         return;
  113.  
  114.     Curschar->linep->prev = l;    /* link neighbors to new line */
  115.     if (prev != NULL)
  116.         prev->linep->next = l;
  117.  
  118.     l->next = Curschar->linep;    /* link new line to neighbors */
  119.     if (prev != NULL)
  120.         l->prev = prev->linep;
  121.  
  122. #if 0
  123.     if (can_ai && P(P_AI)) {
  124.         did_ai = TRUE;
  125.     }
  126. #endif
  127.  
  128.     *Curschar = *prevline(Curschar);    /* cursor moves up */
  129.     Curschar->index = 0;
  130.  
  131.     if (prev == NULL)            /* new start of file */
  132.         Filemem->linep = l;
  133.  
  134.     renum();    /* keep it simple - we don't do this often */
  135.  
  136.     cursupdate();            /* update Cursrow before insert */
  137.     if (Cursrow != 0)
  138.         s_ins(Cursrow, 1);        /* insert a physical line */
  139.  
  140.     updatescreen();
  141. }
  142.  
  143. int
  144. cntllines(pbegin,pend)
  145. LPTR *pbegin, *pend;
  146. {
  147.     LINE *lp;
  148.     int lnum = 1;
  149.  
  150.     for (lp = pbegin->linep; lp != pend->linep ;lp = lp->next)
  151.         lnum++;
  152.  
  153.     return(lnum);
  154. }
  155.  
  156. /*
  157.  * plines(p) - return the number of physical screen lines taken by line 'p'
  158.  */
  159. int
  160. plines(p)
  161. LPTR    *p;
  162. {
  163.     register int    col;
  164.     register char    *s;
  165.  
  166.     s = p->linep->s;
  167.  
  168.     if (*s == NUL)        /* empty line */
  169.         return 1;
  170.  
  171.     /*
  172.      * If list mode is on, then the '$' at the end of
  173.      * the line takes up one extra column.
  174.      */
  175.     col = P(P_LS) ? 1 : 0;
  176.  
  177.     for (; *s != NUL ;s++) {
  178.         if ( *s == TAB && !P(P_LS))
  179.             col += P(P_TS) - (col % P(P_TS));
  180.         else
  181.             col += chars[(unsigned)(*s & 0xff)].ch_size;
  182.     }
  183.     return ((col + (Columns-1)) / Columns);
  184. }
  185.  
  186. void
  187. fileinfo()
  188. {
  189.     long    l1, l2;
  190.     char    buf[80];
  191.  
  192.     if (bufempty()) {
  193.         msg("Buffer Empty");
  194.         return;
  195.     }
  196.  
  197.     l1 = cntllines(Filemem, Curschar);
  198.     l2 = cntllines(Filemem, Fileend) - 1;
  199.     sprintf(buf, "\"%s\"%s line %ld of %ld -- %ld %% --",
  200.         (Filename != NULL) ? Filename : "No File",
  201.         Changed ? " [Modified]" : "",
  202.         l1, l2, (l1 * 100)/l2);
  203.     msg(buf);
  204. }
  205.  
  206. /*
  207.  * gotoline(n) - return a pointer to line 'n'
  208.  *
  209.  * Returns a pointer to the last line of the file if n is zero, or
  210.  * beyond the end of the file.
  211.  */
  212. LPTR *
  213. gotoline(n)
  214. int n;
  215. {
  216.     static    LPTR    l;
  217.  
  218.     l.index = 0;
  219.  
  220.     if ( n == 0 )
  221.         l = *prevline(Fileend);
  222.     else {
  223.         LPTR    *p;
  224.  
  225.         for (l = *Filemem; --n > 0 ;l = *p)
  226.             if ((p = nextline(&l)) == NULL)
  227.                 break;
  228.     }
  229.     return &l;
  230. }
  231.  
  232. void
  233. inschar(c)
  234. int    c;
  235. {
  236.     register char    *p, *pend;
  237.  
  238.     /* make room for the new char. */
  239.     if ( ! canincrease(1) )
  240.         return;
  241.  
  242.     p = &Curschar->linep->s[strlen(Curschar->linep->s) + 1];
  243.     pend = &Curschar->linep->s[Curschar->index];
  244.  
  245.     for (; p > pend ;p--)
  246.         *p = *(p-1);
  247.  
  248.     *p = c;
  249.  
  250.     /*
  251.      * If we're in insert mode and showmatch mode is set, then
  252.      * check for right parens and braces. If there isn't a match,
  253.      * then beep. If there is a match AND it's on the screen, then
  254.      * flash to it briefly. If it isn't on the screen, don't do anything.
  255.      */
  256.     if (P(P_SM) && State == INSERT && (c == ')' || c == '}' || c == ']')) {
  257.         LPTR    *lpos, csave;
  258.  
  259.         if ((lpos = showmatch()) == NULL)    /* no match, so beep */
  260.             beep();
  261.         else if (LINEOF(lpos) >= LINEOF(Topchar)) {
  262.             updatescreen();        /* show the new char first */
  263.             csave = *Curschar;
  264.             *Curschar = *lpos;    /* move to matching char */
  265.             cursupdate();
  266.             windgoto(Cursrow, Curscol);
  267.  
  268. /* added for turbo c port 6-14-88 dlm */
  269.  
  270. #ifdef TURBO
  271.             mdelay();        /* brief pause */
  272. #else
  273.                         delay();
  274. #endif
  275.             *Curschar = csave;    /* restore cursor position */
  276.             cursupdate();
  277.         }
  278.     }
  279.  
  280.     inc(Curschar);
  281.     CHANGED;
  282. }
  283.  
  284. void
  285. insstr(s)
  286. register char *s;
  287. {
  288.     register char *p, *endp;
  289.     register int k, n = strlen(s);
  290.  
  291.     /* Move everything in the file over to make */
  292.     /* room for the new string. */
  293.     if (!canincrease(n))
  294.         return;
  295.  
  296.     endp = &Curschar->linep->s[Curschar->index];
  297.     p = Curschar->linep->s + strlen(Curschar->linep->s) + 1 + n;
  298.  
  299.     for (; p>endp ;p--)
  300.         *p = *(p-n);
  301.  
  302.     p = &Curschar->linep->s[Curschar->index];
  303.     for ( k=0; k<n; k++ ) {
  304.         *p++ = *s++;
  305.         inc(Curschar);
  306.     }
  307.     CHANGED;
  308. }
  309.  
  310. bool_t
  311. delchar(fixpos)
  312. bool_t    fixpos;        /* if TRUE, fix the cursor position when done */
  313. {
  314.     register int i;
  315.  
  316.     /* Check for degenerate case; there's nothing in the file. */
  317.     if (bufempty())
  318.         return FALSE;
  319.  
  320.     if (lineempty())    /* can't do anything */
  321.         return FALSE;
  322.  
  323.     /* Delete the char. at Curschar by shifting everything */
  324.     /* in the line down. */
  325.     for ( i=Curschar->index+1; i < Curschar->linep->size ;i++)
  326.         Curschar->linep->s[i-1] = Curschar->linep->s[i];
  327.  
  328.     /* If we just took off the last character of a non-blank line, */
  329.     /* we don't want to end up positioned at the newline. */
  330.     if (fixpos) {
  331.         if (gchar(Curschar)==NUL && Curschar->index>0 && State!=INSERT)
  332.             Curschar->index--;
  333.     }
  334.     CHANGED;
  335.  
  336.     return TRUE;
  337. }
  338.  
  339.  
  340. void
  341. delline(nlines)
  342. {
  343.     register LINE *p, *q;
  344.     int    doscreen = TRUE;    /* if true, update the screen */
  345.  
  346.     /*
  347.      * There's no point in keeping the screen updated if we're
  348.      * deleting more than a screen's worth of lines.
  349.      */
  350.     if (nlines > (Rows - 1)) {
  351.         doscreen = FALSE;
  352.         s_del(Cursrow, Rows-1);    /* flaky way to clear rest of screen */
  353.     }
  354.  
  355.     while ( nlines-- > 0 ) {
  356.  
  357.         if (bufempty())            /* nothing to delete */
  358.             break;
  359.  
  360.         if (buf1line()) {        /* just clear the line */
  361.             Curschar->linep->s[0] = NUL;
  362.             Curschar->index = 0;
  363.             break;
  364.         }
  365.  
  366.         p = Curschar->linep->prev;
  367.         q = Curschar->linep->next;
  368.  
  369.         if (p == NULL) {        /* first line of file so... */
  370.             Filemem->linep = q;    /* adjust start of file */
  371.             Topchar->linep = q;    /* and screen */
  372.         } else
  373.             p->next = q;
  374.         q->prev = p;
  375.  
  376.         clrmark(Curschar->linep);    /* clear marks for the line */
  377.  
  378.         /*
  379.          * Delete the correct number of physical lines on the screen
  380.          */
  381.         if (doscreen)
  382.             s_del(Cursrow, plines(Curschar));
  383.  
  384.         /*
  385.          * If deleting the top line on the screen, adjust Topchar
  386.          */
  387.         if (Topchar->linep == Curschar->linep)
  388.             Topchar->linep = q;
  389.  
  390.         free(Curschar->linep->s);
  391.         free(Curschar->linep);
  392.  
  393.         Curschar->linep = q;
  394.         Curschar->index = 0;        /* is this right? */
  395.         CHANGED;
  396.  
  397.         /* If we delete the last line in the file, back up */
  398.         if ( Curschar->linep == Fileend->linep) {
  399.             Curschar->linep = Curschar->linep->prev;
  400.             /* and don't try to delete any more lines */
  401.             break;
  402.         }
  403.     }
  404. }
  405.